package cn.hg.solon.youcan.common.web;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.convert.Convert;
import org.dromara.hutool.core.reflect.FieldUtil;
import org.dromara.hutool.core.text.CharSequenceUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.noear.solon.core.handle.Result;

import cn.hg.solon.youcan.common.constant.AppConstants;
import cn.hg.solon.youcan.common.vo.BaseVo;

/**
 * Layui DTree控件结果对象
 * <p>
 * https://www.wisdomelon.com/DTreeHelper/
 * </p>
 *
 * @author 胡高
 */
public class LayuiDtree<T extends Serializable> extends BaseVo {

    /**
     * 树状选择项VO
     *
     * @author 胡高
     * @date 2021/12/20
     */
    public static class LayuiDtreeItem<T> extends BaseVo {

        /**
         * serialVersionUID
         */
        private static final long serialVersionUID = 726646408826889101L;

        /**
         * ID
         */
        private Object id;

        /**
         * 标题
         */
        private String title;

        /**
         * 父ID
         */
        private Object parentId;

        /**
         * 是否叶子节点
         */
        private boolean last;

        /**
         * 子项列表
         */
        private List<LayuiDtreeItem<T>> children;

        public LayuiDtreeItem(T bean, String idField, String parentIdField, String titleField) {
            this.id = FieldUtil.getFieldValue(bean, idField);
            this.parentId = FieldUtil.getFieldValue(bean, parentIdField);
            this.title = Convert.toStr(FieldUtil.getFieldValue(bean, titleField));
        }

        /**
         * @return the children
         */
        public List<LayuiDtreeItem<T>> getChildren() {
            return this.children;
        }

        /**
         * @return the id
         */
        public Object getId() {
            return this.id;
        }

        /**
         * @return the parentId
         */
        public Object getParentId() {
            return this.parentId;
        }

        /**
         * @return the title
         */
        public String getTitle() {
            return this.title;
        }

        /**
         * @return the last
         */
        public boolean isLast() {
            return this.last;
        }

        /**
         * @param children
         *            the children to set
         */
        protected void setChildren(List<LayuiDtreeItem<T>> children) {
            this.children = children;
            this.last = CollUtil.isEmpty(this.children);
        }

    }

    /**
     * @author 胡高
     * @date 2021/12/20
     */
    public static class LayuiDtreeStatus extends BaseVo {

        /**
         * serialVersionUID
         */
        private static final long serialVersionUID = -2455980049163667327L;

        /**
         * 结果代码
         */
        private int code = Result.SUCCEED_CODE;

        /**
         * 结果信息
         */
        private String message = AppConstants.RETURN_MESSAGE_VALUE_SUCCESSED;

        public LayuiDtreeStatus() {

        }

        /**
         * @param code
         *            结果代码
         * @param message
         *            结果信息
         */
        public LayuiDtreeStatus(int code, String message) {
            this.code = code;
            this.message = message;
        }

        /**
         * @return the code
         */
        public int getCode() {
            return this.code;
        }

        /**
         * @return the message
         */
        public String getMessage() {
            return this.message;
        }

        /**
         * @param code
         *            the code to set
         */
        public void setCode(int code) {
            this.code = code;
        }

        /**
         * @param message
         *            the message to set
         */
        public void setMessage(String message) {
            this.message = message;
        }

    }

    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = 9003529846620543270L;

    /**
     * 树对象数组
     */
    private List<LayuiDtreeItem<T>> data;

    /**
     * 结果状态对象
     */
    private LayuiDtreeStatus status;

    /**
     * 创建树对象
     *
     * @param code
     *            结果代码
     * @param message
     *            结果信息
     */
    public LayuiDtree(int code, String message) {
        this.status = new LayuiDtreeStatus(code, message);
    }

    /**
     * 通过ID字段名、上级ID字段名、name字段名、初始顶层ID值创建树对象
     *
     * @param beanList
     *            bean对象列表
     * @param idField
     *            ID字段名
     * @param parentIdField
     *            上级字段名
     * @param nameField
     *            name字段名
     * @param parentIdValue
     *            初始顶层ID值
     */
    public LayuiDtree(List<T> beanList, String idField, String parentIdField, String titleField, Object parentIdValue) {
        this.status = new LayuiDtreeStatus();

        // 转换项目列表为树状选择项列表
        List<LayuiDtreeItem<T>> itemList = this.convertToItemList(beanList, CharSequenceUtil.toCamelCase(idField),
            CharSequenceUtil.toCamelCase(parentIdField), CharSequenceUtil.toCamelCase(titleField), parentIdValue);

        // 构建树状对象
        this.data = this.buildTree(itemList, parentIdValue);
    }

    private List<LayuiDtreeItem<T>> buildTree(final List<LayuiDtreeItem<T>> beanList, Object parentId) {
        List<LayuiDtreeItem<T>> data = new ArrayList<>();

        for (LayuiDtreeItem<T> item : beanList) {

            if (ObjUtil.equals(parentId, item.getParentId())) {
                data.add(item);
            }

        }

        for (LayuiDtreeItem<T> org : data) {
            org.setChildren(this.buildTree(beanList, org.getId()));
        }

        return data;
    }

    private List<LayuiDtreeItem<T>> convertToItemList(List<T> list, String idName, String parentIdName,
        String titleName, Object initParentId) {
        List<LayuiDtreeItem<T>> itemList = new ArrayList<>();
        for (T bean : list) {
            itemList.add(new LayuiDtreeItem<>(bean, idName, parentIdName, titleName));
        }

        return itemList;
    }

    /**
     * @return the data
     */
    public List<LayuiDtreeItem<T>> getData() {
        return this.data;
    }

    /**
     * @return the status
     */
    public LayuiDtreeStatus getStatus() {
        return this.status;
    }

    /**
     * @param status
     *            the status to set
     */
    public void setStatus(LayuiDtreeStatus status) {
        this.status = status;
    }
}
